package ms.jasim.console;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import ms.spm.IAppContext;
import ms.utils.JacrimException;

public class Console extends JasimClient {

	public Console(IAppContext context) throws IOException {
		super(context);
	}

	protected void validateConnection() throws JacrimException {
		if (! Connected())
			throw new JacrimException("Connection is closed.");
	}
	
	public void processUserInput() throws Exception {
		BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

		System.out.printf("[%s]:", ServerUrl());
		
		for (String userInput = stdIn.readLine(); !("quit".equalsIgnoreCase(userInput)); userInput = stdIn.readLine())
			try {
				if (userInput != null) {
					String[] cmds = userInput.split(" ", 2);
					
					if ("add".equalsIgnoreCase(cmds[0]))
						add(userInput);
					else if ("remove".equalsIgnoreCase(cmds[0]))
						remove(userInput);
					else if ("connect".equalsIgnoreCase(cmds[0]))
						connect("localhost", 6668);
					else if ("disconnect".equalsIgnoreCase(cmds[0]))
						shutdown();
					else if (userInput.startsWith("fulfill"))
						fulfill(userInput);
					else if (userInput.startsWith("view"))
						view(userInput);
					else if ("clear".equalsIgnoreCase(userInput))
						clear();
					else if ("fail".equalsIgnoreCase(cmds[0]))
						fail(cmds);
					else if ("quit".equalsIgnoreCase(userInput))
						break;
					else if (userInput.length() > 0)
						System.out.println("Unknown user command: " + userInput);
				} else
					break; // user press Ctrl+C
			} catch (JacrimException e) {
				System.out.println(e.getLocalizedMessage());
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				System.out.printf("[%s]:", ServerUrl());
			}
			
	}

	private void fail(String[] cmds) throws JacrimException, IOException {
		validateConnection();

		if (cmds.length != 2 || (cmds.length > 1 && cmds[1].equals("?"))) {
			showHelp("fail");
			return;
		}
		sendCommand(cmds[0] + " " + cmds[1]);
	}

	private void clear() {
		for (int i = 0; i < 80; i++)
			System.out.println();
	}

	private void view(String userInput) throws IOException, JacrimException {
		validateConnection();
		String[] cmds = userInput.split(" ", 2);
		
		if (cmds.length > 1 && "?".equalsIgnoreCase(cmds[1])) {
			showHelp("view");
			return;
			
		}
		sendCommand(userInput);
		System.out.println("----------------------------");
		for (boolean done = false; !done;) {
			String response = readString();
			
			if (!(done = "DONE".equalsIgnoreCase(response))) {
				if (!response.startsWith("AGENT"))
					System.out.print("\t");
				System.out.println(response);
			}
		}
		System.out.println("----------------------------");
		commandMode();
	}

	private void fulfill(String userInput) throws JacrimException, IOException {
		validateConnection();
		String[] cmds = userInput.split(" ", 2);

		if (cmds.length != 2 || (cmds.length > 1 && cmds[1].equals("?"))) {
			showHelp("fulfill");
			return;
		} 
		if (!sendCommand(userInput))
			System.out.println("Error");
	}

	private void add(String userInput) throws IOException, JacrimException {
		validateConnection();
		String[] cmds = userInput.split(" ");
		
		if (cmds.length == 1 || cmds[1].equals("?")) {
			showHelp("add");
			return;
		}
		
		sendCommand(userInput);
	}
	
	private void remove(String userInput) throws IOException, JacrimException {
		validateConnection();
		String[] cmds = userInput.split(" ");

		if (cmds.length == 1 || cmds[1].equals("?")) {
			showHelp("remove");
			return;
		}

		sendCommand(userInput);
	}
	
	private void showHelp(String cmd) {
		if ("add".equalsIgnoreCase(cmd)) {
			System.out.println("Syntax:");
			System.out.println("\tadd percept <agent name> <percept>: add an percept to an agent.");
		} else if ("remove".equalsIgnoreCase(cmd)) {
			System.out.println("Syntax:");
			System.out.println("\tremove percept <agent name> <percept>: remove an percept from an agent.");
		}
		else if ("view".equalsIgnoreCase(cmd)) {
			System.out.println("Syntax:");
			System.out.println("\tview [status]: display executing status of all agents.");
			System.out.println("\tview mind <agent name>: display current belief base of a agent.");
			System.out
					.println("\tview plan [all]: display current solution. If [all] is not specify, only display executing and finished actions.");
		}
		else if ("fulfill".equalsIgnoreCase(cmd)) {
			System.out.println("Syntax:");
			System.out.println("\tfulfill <goal name>: inform that the given goal has been fulfilled.");
		}
	}

	
	public static void main(String[] args) {
		try {
			System.setProperty("java.security.policy", "java.policy");
			Console c = new Console(ms.spm.implement.SimpleAppContext.createRootContext());
			System.out.println("Connect to JasimServer....");
			c.connect("localhost", 6668);
			c.processUserInput();
			c.shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}

}
